package com.ltmonitor.jt808.service.impl;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ltmonitor.dao.IOnlineRecordDao;
import com.ltmonitor.entity.AlarmRecord;
import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.entity.OnlineRecord;
import com.ltmonitor.jt808.service.IAlarmService;
import com.ltmonitor.jt808.service.INewAlarmService;
import com.ltmonitor.jt808.service.IOnlineAnalyzeService;
import com.ltmonitor.service.ILocationService;
import com.ltmonitor.service.IOnlineRecordService;
import com.ltmonitor.util.DateUtil;
import com.ltmonitor.util.StringUtil;

/**
 * 车载终端上线记录分析服务
 * 
 * @author DELL
 * 
 */
@Service("onlineAnalyzeService")
public class OnlineAnalyzeService implements IOnlineAnalyzeService {
	//@Autowired
	//private IOnlineRecordDao onlineRecordDao;

	@Autowired
	private IOnlineRecordService onlineRecordService;
	
	@Autowired
	private ILocationService locationService;

	private Thread processRealDataThread;
	@Autowired
	private IAlarmService alarmService;
	private static Logger logger = Logger.getLogger(OnlineAnalyzeService.class);
	private ConcurrentLinkedQueue<OnlineRecord> dataQueue = new ConcurrentLinkedQueue();

	private ConcurrentMap<String, Boolean> onlineMap = new ConcurrentHashMap<String, Boolean>();
	/**
	 * 车辆上线状态 map״̬
	 */
	private ConcurrentMap<String, Boolean> connectedStateMap = new ConcurrentHashMap<String, Boolean>();

	@Autowired
	private INewAlarmService newAlarmService;

	private boolean startAnalyze = true;

	public OnlineAnalyzeService() {
		processRealDataThread = new Thread(new Runnable() {
			public void run() {
				processRealDataThreadFunc();
			}
		});

		processRealDataThread.start();

	}

	@Override
	public void stopService() {
		startAnalyze = false;
		try {
			processRealDataThread.join(50000);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		// processRealDataThread.stop();
	}

	private void processRealDataThreadFunc() {
		while (startAnalyze) {
			try {
				OnlineRecord tm = dataQueue.poll();
				while (tm != null) {
					try {
						Date start = new Date();
						if (alarmService.isAlarmEnabled(tm.getAlarmType(),
								AlarmRecord.ALARM_FROM_PLATFORM)) {
						    createOnlineChangeRecord(tm);
						}
						String alarmType = tm.getAlarmType().equals(
								OnlineRecord.TYPE_ONLINE) ? OnlineRecord.TYPE_OFFLINE
								: OnlineRecord.TYPE_ONLINE;
						tm.setAlarmType(alarmType);
						tm.setStatus(OnlineRecord.STATUS_OLD);

						if (alarmService.isAlarmEnabled(alarmType,
								AlarmRecord.ALARM_FROM_PLATFORM)) {
						    createOnlineChangeRecord(tm);
						}

						Date end = new Date();
						double seconds = DateUtil.getSeconds(start, end);
						if (seconds > 2)
							logger.error("创建上下线记录时间:" + seconds);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}

					tm = dataQueue.poll();
				}

			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}

			try {
				Thread.sleep(500L);
			} catch (InterruptedException e1) {
			}
		}
	}

	public void UpdateConnectedState(String simNo, Boolean isConnected) {
		this.connectedStateMap.put(simNo, isConnected);
	}

	public Boolean isConnected(String simNo) {
		if (connectedStateMap.containsKey(simNo)) {
			return connectedStateMap.get(simNo);
		}
		return false;
	}

	public void checkOnline(GPSRealData rd) {
		//boolean oldState = false;
		//if (onlineMap.containsKey(rd.getSimNo())) {
			//oldState = onlineMap.get(rd.getSimNo());
		//}
		boolean online = rd.getOnline();
		OnlineRecord r = new OnlineRecord();
		r.setPlateNo(rd.getPlateNo());
		r.setLatitude(rd.getLatitude());
		r.setLongitude(rd.getLongitude());
		r.setStartTime(rd.getOnlineDate());
		r.setLocation(rd.getLocation());
		r.setVehicleId(rd.getVehicleId());
		r.setVelocity(rd.getVelocity());
		String alarmType = rd.getOnline() ? OnlineRecord.TYPE_ONLINE
				: OnlineRecord.TYPE_OFFLINE;
		r.setAlarmType(alarmType);

		if (alarmService.isAlarmEnabled(alarmType,
				AlarmRecord.ALARM_FROM_PLATFORM)) {
			this.newAlarmService.insertAlarm(AlarmRecord.ALARM_FROM_PLATFORM,
					alarmType, rd);
		}

		if (dataQueue.size() > 2000) {
			logger.error("上下线记录分析服务队列堵塞" + dataQueue.size());
			dataQueue.clear();
		}
		dataQueue.add(r);
		onlineMap.put(rd.getSimNo(), online);
		// }
	}

	/**
	 * 创建上下线记录库表
	 * @param rd
	 */
	@Transactional
	public void createOnlineChangeRecord(OnlineRecord rd) {
		String alarmType = rd.getAlarmType();
		String hsql = "from OnlineRecord rec where rec.plateNo = ? and rec.status = ? and rec.alarmType = ?";
		// 查看是否有未消除的报警
		OnlineRecord sr = (OnlineRecord) onlineRecordService.find(
				hsql,
				new String[] { rd.getPlateNo(), OnlineRecord.STATUS_NEW,
						alarmType });

		if (sr == null && OnlineRecord.STATUS_NEW.equals(rd.getStatus())) {
			// this.insertAlarm(OnlineRecord.ALARM_FROM_PLATFORM, alarmType,
			// rd);

			sr = new OnlineRecord();
			sr.setVehicleId(rd.getVehicleId());
			sr.setPlateNo(rd.getPlateNo());
			sr.setStartTime(rd.getStartTime());
			sr.setStatus(OnlineRecord.STATUS_NEW);
			sr.setEndTime(new Date());
			sr.setLatitude(rd.getLatitude());
			sr.setLongitude(rd.getLongitude());

			String location = rd.getLocation();
			if (StringUtil.isNullOrEmpty(location))
				location = locationService.getLocation(sr.getLatitude(),
						sr.getLongitude());
			sr.setLocation(location);
			sr.setVelocity(rd.getVelocity());
			sr.setAlarmType(alarmType);
			onlineRecordService.saveOrUpdate(sr);

		} else if (OnlineRecord.STATUS_OLD.equals(rd.getStatus()) && sr != null) {
			sr.setEndTime(rd.getStartTime());
			double t = DateUtil.getSeconds(sr.getStartTime(), sr.getEndTime()) / 60;
			sr.setTimeSpan(t);

			sr.setStatus(OnlineRecord.STATUS_OLD);
			// sr.setEndTime(new Date());// rd.SendTime;
			sr.setLatitude1(rd.getLatitude());
			sr.setLongitude1(rd.getLongitude());

			sr.setAlarmType(alarmType);
			onlineRecordService.saveOrUpdate(sr);
		}
	}


}
